namespace("jclass.graphics.p3d")
({
    P3D : jClass({
        constructor : function(canvas, obj) {
            _canvas = canvas;
            if (obj) {
                loadObject(obj)
            }
        },
        private : {
            colors: color = { r:112, g:146, b:190 },
            _canvas : undefined,
            _obj : '',
            x : 0, y : 0,
            rgbR : 0,
            rgbG : 0,
            rgbB : 0,
            _000 : 0,
            width : 0,
            height : 0,
            heightMiddle : 0,
            widthMiddle : 0,
            _005 : 0,
            _006 : 0,
            rotateSlowFactor : 0,
            pointVlength : 0,
            pointFlength : 0,
            _011 : 0,
            _012 : undefined,
            _013 : undefined,
            _014 : undefined,
             _017 : undefined,
            pointV : undefined,
            pointF : undefined,

            loadObject : function(obj) {
                _obj = obj;

                rgbR = colors.r;
                rgbG = colors.g;
                rgbB = colors.b;

                _000 = 0.0;
                width = _canvas.getAttribute("width");
                height = _canvas.getAttribute("height");
                widthMiddle = width / 2;
                heightMiddle = height / 2;

                _005 = 0.20000000000000001;
                _006 = 0.29999999999999999;

                rotateSlowFactor = 0.08;

                parseData();

                pointVlength = pointV.length;
                pointFlength = pointF.length;

                for (var i = 0; i < pointVlength; i++) {
                    var d1 = pointV[i].x * pointV[i].x + pointV[i].y * pointV[i].y + pointV[i].z * pointV[i].z;
                    if (_000 < d1) _000 = d1;
                }

                _011 = heightMiddle / Math.sqrt(_000);
                _014 = new Array();
                for (var l  = 0; l < pointFlength; l++) {
                    if (_014[l] === undefined) _014[l] = [];
                    _014[l][0] =  (pointV[pointF[l][1]].y - pointV[pointF[l][0]].y) * (pointV[pointF[l][2]].z -
                                   pointV[pointF[l][1]].z) - (pointV[pointF[l][2]].y - pointV[pointF[l][1]].y) *
                                  (pointV[pointF[l][1]].z - pointV[pointF[l][0]].z);
                    _014[l][1] = -(pointV[pointF[l][1]].x - pointV[pointF[l][0]].x) * (pointV[pointF[l][2]].z -
                                  pointV[pointF[l][1]].z) + (pointV[pointF[l][2]].x - pointV[pointF[l][1]].x) *
                                  (pointV[pointF[l][1]].z - pointV[pointF[l][0]].z);
                    _014[l][2] =  (pointV[pointF[l][1]].x - pointV[pointF[l][0]].x) * (pointV[pointF[l][2]].y -
                                   pointV[pointF[l][1]].y) - (pointV[pointF[l][2]].x - pointV[pointF[l][1]].x) *
                                   (pointV[pointF[l][1]].y - pointV[pointF[l][0]].y);

                    var d2 = Math.sqrt(_014[l][0] * _014[l][0] + _014[l][1] * _014[l][1] + _014[l][2] * _014[l][2]) / 255.5;

                    _014[l][0] /= d2;
                    _014[l][1] /= d2;
                    _014[l][2] /= d2;
                }

                for (var x = 0; x < 256; x++) {
                    var r, g, b;
                    r = x <= colors['r'] ? x : colors['r'];
                    g = x <= colors['g'] ? x : colors['r'];
                    b = x <= colors['b'] ? x : colors['r'];
                    _012[x] = [r,g,b];
                }
                init();
                _canvas.onmousedown = onmousedown
            },

            onmousedown : function() {
                _canvas.onmousemove = onmousemove;
                _canvas.onmouseup = onmouseup;
                _canvas.onmouseout = onmouseup;
            },

            onmousemove : function(event) {
                var deltaX = x - event.clientX;
                var deltaY = y -  event.clientY;
                rotate(deltaX, deltaY);
                x = event.clientX;
                y = event.clientY;
            },

            onmouseup : function() {
                _canvas.onmousemove = undefined;
                _canvas.onmouseup = undefined;
                _canvas.onmouseout = undefined;
            },

            reset : function() {
                width = _canvas.width;
                height = _canvas.height;
                widthMiddle = width / 2;
                heightMiddle = height / 2;

                for (var i = 0; i < pointVlength; i++) {
                    var d1 = pointV[i].x * pointV[i].x + pointV[i].y * pointV[i].y + pointV[i].z * pointV[i].z;
                    if (_000 < d1) _000 = d1;
                }
                _011 = heightMiddle / Math.sqrt(_000);
                init();
            },

            init : function() {
                var d  = Math.cos(_005);
                var d1 = Math.cos(_006);
                var d2 = Math.sin(_005);
                var d3 = Math.sin(_006);
                var d4 = _011 * d1;
                var d5 = _011 * d3;
                var d6 = _011 * d2 * d3;
                var d7 = _011 * d;
                var d8 = -_011 * d2 * d1;
                var d9 = -d * d3;
                var d10 = d2;
                var d11 = d * d1;
                _017 = new Array();
                for(var i = 0; i < pointVlength; i++) {
                    if (_017[i] === undefined) _017[i] = [];

                    _017[i][0] = d4 * pointV[i].x + d5 * pointV[i].z;
                    _017[i][1] = d6 * pointV[i].x + d7 * pointV[i].y + d8 * pointV[i].z;
                }
                _013 = new Array();
                for(var j = 0; j < pointFlength; j++) {
                    _013[j] = d9 * _014[j][0] + d10 * _014[j][1] + d11 * _014[j][2];
                }
                draw();
            },

            draw : function() {
                var bd = _canvas.getContext('2d');
                bd.clearRect(0,0, width, height);
                bd.strokeStyle = "black";
                bd.lineWidth = 1;
                for (var i = 0; i < pointFlength; i++) {
                    if (_013[i] > 0.0) {
                        var point = [];
                        for (var j = 0; j < pointF[i].length; j++) {
                            point.push({x:heightMiddle + _017[pointF[i][j]][0], y:widthMiddle  + _017[pointF[i][j]][1]});
                        }
                        var color = 0xff00ff;
                        drawPoly(bd, point, color)
                    }
                }
            },

            drawPoly : function(context, points, color) {
                context.beginPath();
                context.moveTo(points[0].x, points[0].y);
                points.forEach(function(point){
                    context.lineTo(point.x, point.y);
                });
                context.fillStyle = "rgb("+rgbR+","+rgbG+","+rgbB+")";
                context.fill();
                context.closePath();
                context.stroke();
            },

            rotate : function(x, y) {
                _005 += x * rotateSlowFactor;
			    _006 += y * rotateSlowFactor;
			    reset();
            },

            parseData : function(){
                function trim(val) {
                    return (val || "").replace( /^(\s|\u00A0)+|(\s|\u00A0)+$/g, "" );
                }
                var actualData  = trim(_obj.substr(_obj.indexOf("#")));
                var vertex = trim(actualData).split("#");
                var face1 = vertex[1].split(",");
                var face2 = vertex[2].split("-1");
                var tmp, i,j;
                
                pointV = new Array();
                pointF = new Array();

                for (i = 0; i < face1.length; i++) {
                    tmp = face1[i].split(" ");
                    pointV[i] = {x:tmp[1], y:tmp[2], z:tmp[3]};
                }
                for (i = 0; i < face2.length; i++) {
                    tmp = face2[i].split(" ");
                    for (j = 0; j < tmp.length - 2; j++) {
                        if (pointF[i] === undefined) {
                            pointF[i] = [];
                        }
                        pointF[i][j] = tmp[j + 1];
                    }
                }
            }
        },
        public : {
            Load : function(obj) {
                loadObject(obj)
            },
            Rotate : function(x, y) {
                rotate(x,y)
            }
       }
    })
});